﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using Jack.DataScience.Data.Converters;
using Vav.Data.TransferTypes;
using Vav.Data.Utils;
using System.ComponentModel;
using Vav.Data.WeChat;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.IO;
using Newtonsoft.Json.Linq;
using Vav.Data.Payment;
using CarPool.Data.Models;

namespace Vav.Data.DataAccess
{
    public class WeChatDataAccess
    {
        private readonly VavdbContext context;

        public WeChatDataAccess(VavdbContext vavdbContext)
        {
            this.context = vavdbContext;
        }
        /// <summary>
        /// 全局唯一的获取微信access_token 入口
        /// </summary>
        /// <param name="appid"></param>
        /// <returns></returns>
        public async Task<string> GetAccessToken(string appid)
        {
            var wechat = context.WechatInfo.FirstOrDefault(w => w.Appid == appid);
            if (wechat != null)
            {
                if (!string.IsNullOrWhiteSpace(wechat.AccessToken) && wechat.Expirestime > DateTime.Now)
                {
                    if (await WeChatBase.CheckAccessToken(wechat.AccessToken))
                    {
                        return wechat.AccessToken;
                    }
                }
                var res = await WeChatBase.GetAccessToken(wechat.Appid, wechat.Appsecret);
                if (!string.IsNullOrWhiteSpace(res.access_token))
                {
                    wechat.AccessToken = res.access_token;
                    wechat.Expirestime = DateTime.Now.AddHours(2);
                    context.Update(wechat);
                    context.SaveChanges();
                    return res.access_token;
                }
            }
            return "";
        }
        /// <summary>
        /// 统一下单
        /// </summary>
        /// <param name="weChatUnifiedOrder"></param>
        /// <param name="paySecret">支付密钥</param>
        /// <returns></returns>
        public async Task<PurchaseReportResponse> Unifiedorder(WeChatUnifiedOrder weChatUnifiedOrder, string paySecret)
        {
            return await WeChatRequest.BuildWeChatPay(weChatUnifiedOrder, paySecret);
        }
        #region 小程序
        /// <summary>
        /// 获取微信小程序微信uniodId
        /// </summary>
        /// <param name="appid"></param>
        /// <param name="code"></param>
        /// <returns></returns>
        public async Task<ProUserUnionId> GetProUserUnionId(string appid, string code)
        {
            var wechat = context.WechatInfo.FirstOrDefault(w => w.Appid == appid);
            if (wechat != null)
            {
                var res = await WeChatBase.GetProUserUnionId(wechat.Appid, wechat.Appsecret, code);
                return res;
            }
            return null;
        }
        /// <summary>
        /// 获取微信小程序微信用户信息
        /// </summary>
        /// <param name="appid"></param>
        /// <param name="js_code"></param>
        /// <param name="encryptedData"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        public async Task<ProUserInfo> GetWeChatProUserInfo(string appid, string js_code, string encryptedData, string iv)
        {
            var wechat = context.WechatInfo.FirstOrDefault(w => w.Appid == appid);
            if (wechat != null)
            {
                var res = await WeChatBase.GetProUserUnionId(wechat.Appid, wechat.Appsecret, js_code);
                if (!string.IsNullOrWhiteSpace(res.session_key))
                { //创建解密器生成工具实例  
                    using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider())
                    {
                        //设置解密器参数  
                        aes.Mode = CipherMode.CBC;
                        aes.BlockSize = 128;
                        aes.Padding = PaddingMode.PKCS7;
                        //格式化待处理字符串  
                        byte[] byte_encryptedData = Convert.FromBase64String(encryptedData);
                        byte[] byte_iv = Convert.FromBase64String(iv);
                        byte[] byte_sessionKey = Convert.FromBase64String(res.session_key);

                        aes.IV = byte_iv;
                        aes.Key = byte_sessionKey;
                        //根据设置好的数据生成解密器实例  
                        ICryptoTransform transform = aes.CreateDecryptor();

                        //解密  
                        byte[] final = transform.TransformFinalBlock(byte_encryptedData, 0, byte_encryptedData.Length);

                        //生成结果  
                        string result = Encoding.UTF8.GetString(final);

                        //反序列化结果，生成用户信息实例  
                        var userInfo = result.ToObject<ProUserInfo>();
                        return userInfo;
                    }

                }
            }
            return null;
        }
        /// <summary>
        /// 获取二维码
        /// </summary>
        /// <param name="token"></param>
        /// <param name="scene"></param>
        /// <param name="page"></param>
        /// <returns></returns>
        public async Task<Stream> GetProCode(string token, string scene, string page)
        {
            var stream = await WeChatBase.GetProCode(new GetWxCodeRequest
            {
                is_hyaline = true,
                page = page,
                scene = scene
            }, token);
            return stream;
        }
        public async Task<SendMsg> SendProTemplateMsg(string token, JObject jObject)
        {
            var data = await WeChatBase.SendProTemplateMsg(jObject, token);
            return data;
        }
        #endregion

        #region 公众号
        /// <summary>
        /// 获取微信公众号微信用户信息
        /// </summary>
        /// <param name="appid"></param>
        /// <param name="code"></param>
        /// <returns></returns>
        public async Task<PubUserInfoResponse> GetWeChatPubUserInfo(string appid, string code)
        {
            var wechat = context.WechatInfo.FirstOrDefault(w => w.Appid == appid);
            if (wechat != null)
            {
                var res = await WeChatBase.GetWebAccessToken(wechat.Appid, wechat.Appsecret, code);
                if (!string.IsNullOrWhiteSpace(res.access_token))
                {
                    var userInfo = await WeChatBase.GetPubUserInfo(res.access_token, res.openid);
                    return userInfo;
                }
            }
            return null;
        }
        /// <summary>
        /// 推送微信公众号模板消息
        /// </summary>
        /// <param name="token"></param>
        /// <param name="jObject"></param>
        /// <returns></returns>
        public async Task<SendMsg> SendPubTemplateMsg(string token, JObject jObject)
        {
            var data = await WeChatBase.SendPubTemplateMsg(jObject, token);
            return data;
        }
        #endregion
    }
}
